﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;

namespace Ape.Volo.Common.Extensions;

/// <summary>
/// DataTable扩展
/// </summary>
public static partial class ExtObject
{
    /// <summary>
    /// DataTable转List
    /// </summary>
    /// <typeparam name="T">转换类型</typeparam>
    /// <param name="dt">数据源</param>
    /// <returns></returns>
    public static List<T> ToList<T>(this DataTable dt)
    {
        List<T> list = new List<T>();

        //确认参数有效,若无效则返回Null
        if (dt == null)
            return list;
        if (dt.Rows.Count == 0)
            return list;

        Dictionary<string, string> dicField = new Dictionary<string, string>();
        Dictionary<string, string> dicProperty = new Dictionary<string, string>();
        Type type = typeof(T);

        //创建字段字典，方便查找字段名
        type.GetFields().ForEach(aFiled => { dicField.Add(aFiled.Name.ToLower(), aFiled.Name); });

        //创建属性字典，方便查找属性名
        type.GetProperties().ForEach(aProperty => { dicProperty.Add(aProperty.Name.ToLower(), aProperty.Name); });

        for (int i = 0; i < dt.Rows.Count; i++)
        {
            //创建泛型对象
            T t = Activator.CreateInstance<T>();
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                string memberKey = dt.Columns[j].ColumnName.ToLower();

                //字段赋值
                if (dicField.ContainsKey(memberKey))
                {
                    FieldInfo theField = type.GetField(dicField[memberKey]);
                    var dbValue = dt.Rows[i][j];
                    if (dbValue.GetType() == typeof(DBNull))
                        dbValue = null;
                    if (dbValue != null)
                    {
                        Type memberType = theField.FieldType;
                        dbValue = dbValue.ChangeType_ByConvert(memberType);
                    }

                    theField.SetValue(t, dbValue);
                }

                //属性赋值
                if (dicProperty.ContainsKey(memberKey))
                {
                    PropertyInfo theProperty = type.GetProperty(dicProperty[memberKey]);
                    var dbValue = dt.Rows[i][j];
                    if (dbValue.GetType() == typeof(DBNull))
                        dbValue = null;
                    if (dbValue != null)
                    {
                        Type memberType = theProperty.PropertyType;
                        dbValue = dbValue.ChangeType_ByConvert(memberType);
                    }

                    theProperty.SetValue(t, dbValue);
                }
            }

            list.Add(t);
        }

        return list;
    }

    /// <summary>
    ///将DataTable转换为标准的CSV字符串
    /// </summary>
    /// <param name="dt">数据表</param>
    /// <returns>返回标准的CSV</returns>
    public static string ToCsvStr(this DataTable dt)
    {
        //以半角逗号（即,）作分隔符，列为空也要表达其存在。
        //列内容如存在半角逗号（即,）则用半角引号（即""）将该字段值包含起来。
        //列内容如存在半角引号（即"）则应替换成半角双引号（""）转义，并用半角引号（即""）将该字段值包含起来。
        StringBuilder sb = new StringBuilder();
        DataColumn colum;
        foreach (DataRow row in dt.Rows)
        {
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                colum = dt.Columns[i];
                if (i != 0) sb.Append(",");
                if (colum.DataType == typeof(string) && row[colum].ToString().Contains(","))
                {
                    sb.Append("\"" + row[colum].ToString().Replace("\"", "\"\"") + "\"");
                }
                else sb.Append(row[colum]);
            }

            sb.AppendLine();
        }

        return sb.ToString();
    }
}
